package com.example.user.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.commons.core.domain.BaseResponse;
import com.example.commons.core.entity.UserInfo;
import com.example.commons.core.entity.UserRoleRelation;
import com.example.commons.core.exception.ServiceException;
import com.example.commons.core.vo.receive.AddOrUpdateUserInfoReceiveVo;
import com.example.commons.core.vo.receive.UserInfoReceiveVo;
import com.example.user.form.LoginBody;
import com.example.user.service.UserInfoService;
import com.example.user.service.UserRoleRelationService;
import lombok.extern.log4j.Log4j2;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@RestController
@Log4j2
public class UserInfoController {

    private final UserInfoService userInfoService;
    private final UserRoleRelationService userRoleRelationService;

    public UserInfoController(UserInfoService userInfoService, UserRoleRelationService userRoleRelationService) {
        this.userInfoService = userInfoService;
        this.userRoleRelationService = userRoleRelationService;
    }

    @PostMapping("/login")
    public BaseResponse<SaTokenInfo> login(@RequestBody LoginBody loginBody) throws ServiceException {
//        if(true){
//            throw new ServiceException("用户/密码必须填写");
//        }
        Assert.notNull(loginBody.getUserName(), "用户名不能为空");
        Assert.notNull(loginBody.getPassword(), "密码不能为空");
        UserInfo userInfo = userInfoService.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserName, loginBody.getUserName()).eq(UserInfo::getPassword, loginBody.getPassword()));
        Assert.notNull(userInfo, "用户名或密码错误！");
        StpUtil.login(userInfo.getId());
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        // 保存用户信息到session会话
        StpUtil.getSession().set("userInfo", userInfo);
        return BaseResponse.ok(tokenInfo);
    }

    @PostMapping("/logout")
    public BaseResponse<String> logout() throws ServiceException {
        log.info(String.format("用户%s下线", ((UserInfo) StpUtil.getSession().get("userInfo")).getUserName()));
        StpUtil.logout();
        return BaseResponse.ok("成功下线");
    }

    // 登录校验：只有登录之后才能进入该方法
    @SaCheckLogin
    @PostMapping("/getUserInfo")
    public BaseResponse<UserInfo> getUserInfo() throws ServiceException {
        UserInfo userInfo = (UserInfo) StpUtil.getSession().get("userInfo");
        userInfo.setAuthBtnList(List.of("btn.add", "btn.del", "btn.edit", "btn.link"));
        return BaseResponse.ok(userInfo);
    }

    /**
     * 查询用户信息列表
     *
     * @return 用户信息列表
     */
    // 登录校验：只有登录之后才能进入该方法
    @SaCheckLogin
    @PostMapping("/getUserInfoPage")
    public BaseResponse<IPage<UserInfo>> getUserInfoPage(@RequestBody UserInfoReceiveVo userInfoReceiveVo) {
        IPage<UserInfo> iPage = new Page<>(userInfoReceiveVo.getPageNum(), userInfoReceiveVo.getPageSize());
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(!userInfoReceiveVo.getSearch().isEmpty()){
            lambdaQueryWrapper.like(UserInfo::getUserName, userInfoReceiveVo.getSearch());
        }
        IPage<UserInfo> userInfoIPage = userInfoService.page(iPage, lambdaQueryWrapper);
        // 多角色下可以使用该方法
        /*
        if (userInfoIPage.getRecords().size() > 0) {
            List<Long> userIdList = userInfoIPage.getRecords().stream().map(UserInfo::getId).toList();
            // 查询用户的角色，然后将角色返回给前端
            List<UserRoleRelation> userRoleRelations = userRoleRelationService.list(new LambdaQueryWrapper<UserRoleRelation>().in(UserRoleRelation::getUserId, userIdList));
            Map<Long, List<Long>> userRoleMaps = userRoleRelations.stream().collect(Collectors.groupingBy(UserRoleRelation::getUserId, Collectors.mapping(UserRoleRelation::getRoleId, Collectors.toList())));
            userInfoIPage.getRecords().forEach(x-> x.setRoles(userRoleMaps.get(x.getId())));
        }
        */
        if (userInfoIPage.getRecords().size() > 0) {
            List<Long> userIdList = userInfoIPage.getRecords().stream().map(UserInfo::getId).toList();
            // 查询用户的角色，然后将角色返回给前端
            List<UserRoleRelation> userRoleRelations = userRoleRelationService.list(new LambdaQueryWrapper<UserRoleRelation>().in(UserRoleRelation::getUserId, userIdList));
            Map<Long, Long> userRoleMaps = userRoleRelations.stream().collect(Collectors.toMap(UserRoleRelation::getUserId, UserRoleRelation::getRoleId));
            userInfoIPage.getRecords().forEach(x-> x.setRoleId(userRoleMaps.get(x.getId())));
        }
        return BaseResponse.ok(userInfoIPage);
    }

    /**
     * 查询用户信息列表
     *
     * @return 用户信息列表
     */
    // 登录校验：只有登录之后才能进入该方法
    @SaCheckLogin
    @PostMapping("/getUserInfoList")
    public BaseResponse<List<UserInfo>> getUserInfoList(@RequestBody UserInfoReceiveVo userInfoReceiveVo) {
        return BaseResponse.ok(userInfoService.list(new LambdaQueryWrapper<>()));
    }

    /**
     * 新增用户信息
     *
     * @param userInfo 用户信息
     * @return 成功
     */
    // 登录校验：只有登录之后才能进入该方法
    @SaCheckLogin
    @PostMapping("/addUserInfo")
    public BaseResponse<Void> addOrUpdateUserInfo(@RequestBody AddOrUpdateUserInfoReceiveVo userInfo) {
        UserInfo existUserInfo = userInfoService.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserName, userInfo.getUserName()));
        if (existUserInfo != null) {
            Assert.isTrue(Objects.equals(existUserInfo.getId(), userInfo.getId()), "用户名称重复，请更改后提交！");
        }
        userInfoService.saveOrUpdate(userInfo);
        // 删除用户与角色的关联
        userRoleRelationService.remove(new LambdaQueryWrapper<UserRoleRelation>().eq(UserRoleRelation::getUserId, userInfo.getId()));
        // 新增用户与角色的关联
        userRoleRelationService.save(new UserRoleRelation(userInfo.getId(), userInfo.getRoleId(), LocalDateTime.now()));
        return BaseResponse.ok();
    }

    /**
     * 新增用户信息
     *
     * @param userId 用户信息
     * @return 成功
     */
    // 登录校验：只有登录之后才能进入该方法
    @SaCheckLogin
    @DeleteMapping("/delUserInfo/{userId}")
    public BaseResponse<Void> delUserInfo(@PathVariable("userId") Long userId) {
        userInfoService.removeById(userId);
        return BaseResponse.ok();
    }
}
